package utility;


public class Vector3 extends Vector {

	public static final int X = 0;
	public static final int Y = 1;
	public static final int Z = 2;
	
	public Vector3(double[] elements) {
		super(validate(elements));
	}
	
	private static double[] validate(double[] elements) {
		if(elements == null) {
			throw new IllegalArgumentException("Elements of vector3 can't be null.");
		}
		if(elements.length != 3) {
			throw new IllegalArgumentException("Vector3 must have 3 elements.");
		}
		return elements;
	}
	
	public Vector3 crossProduct(Vector3 other) {
		double x = this.y() * other.z() - this.z() * other.y();
		double y = this.z() * other.x() - this.x() * other.z();
		double z = this.x() * other.y() - this.y() * other.x();
		x = (Math.abs(x) < 0.00001) ? 0.0 : x;
		y = (Math.abs(y) < 0.00001) ? 0.0 : y;
		z = (Math.abs(z) < 0.00001) ? 0.0 : z;
		Vector3 product = new Vector3(new double[]{x, y, z});
		return product;
	}
	
	public static Vector3 midpoint(Vector3 a, Vector3 b) {
		double x = (a.x() + b.x()) / 2.0;
		double y = (a.y() + b.y()) / 2.0;
		double z = (a.z() + b.z()) / 2.0;
		Vector3 midpoint = new Vector3(new double[]{x, y, z});
		return midpoint;
	}
	
	public Vector3 minus(Vector3 other) {
		double[] difference = new double[3];
		for(int i = 0; i < elements.length; i++) {
			difference[i] = elements[i] - other.elements[i];
		}
		return new Vector3(difference);
	}
	
	public Vector3 plus(Vector3 other) {
		double[] sum = new double[3];
		for(int i = 0; i < elements.length; i++) {
			sum[i] = elements[i] + other.elements[i];
		}
		return new Vector3(sum);
	}
	
	public Vector3 scale(double scalar) {
		double[] product = new double[3];
		for(int i = 0; i < elements.length; i++) {
			product[i] = elements[i] * scalar;
		}
		return new Vector3(product);
	}
	public void normalize() {
		double length = getMagnitude();
		elements[0] = x() / length;
		elements[1] = y() / length;
		elements[2] = z() / length;
	}

	public double getMagnitude() {
		double magnitude = Math.sqrt(x()*x() + y()*y() + z()*z());
		return magnitude;
	}
	
	public double distance(Vector3 other) {
		double distance = Math.sqrt(Math.pow(x() - other.x(), 2) + 
				Math.pow(y() - other.y(), 2) + Math.pow(z() - other.z(), 2));
		return distance;
	}
	
	public double x() {
		return elements[X];
	}
	
	public double y() {
		return elements[Y];
	}
	
	public double z() {
		return elements[Z];
	}
	
	public Vector3 clone() {
		return new Vector3(new double[]{this.x(), this.y(), this.z()});
	}
}

